#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <windows.h>


#undef CopyFile
#pragma comment(lib, "kernel32.lib")//yyw

#define DEF_BUF 512

long GetCPUTime() //用于获取此时刻cpu时间
{
	static LARGE_INTEGER li = {0};
	LARGE_INTEGER linow = {0};
	if (li.QuadPart == 0)
		QueryPerformanceFrequency(&li);
	QueryPerformanceCounter(&linow);
	return linow.QuadPart * 10000 / li.QuadPart;
}

#ifdef __TURBOC__               /* Borland   */
#define get_clock_ticks(x) x=biostime(0,0L)
#else                           /* Microsoft and Watcom */
#define get_clock_ticks(x) \
	x = GetCPUTime()//yyw
//        _bios_timeofday(_TIME_GETCLOCK, &x)//yyw
#endif

long CopyFile ( char *infilename, char *outfilename,
            size_t insize, size_t outsize )
//接收参数 源文件名、目标文件名、输入缓冲区大小、输出缓冲区大小，依此完成一次文件复制并返回耗时。
{
    int  c;
    long starttime, donetime;
    FILE *infile, *outfile;

    /* open input file and setup its buffer 提高健壮性 */
    if (( infile = fopen ( infilename, "rb" )) == NULL)
    {
          printf ( "Can't open %s\n", infilename );
          exit ( 1 );
    }

    if ( setvbuf ( infile, NULL, _IOFBF, insize ))
    {
         printf ( "Couldn't set infile buffer to %u bytes.\n",
                   insize );
         exit ( 1 );
    }


    /* open output file and setup its buffer 提高健壮性*/

    if (( outfile = fopen ( outfilename, "wb" )) == NULL )
    {
          printf ( "Can't open %s\n", outfilename );
          exit ( 1 );
    }

    if ( setvbuf ( outfile, NULL, _IOFBF, outsize ))
    {
         printf ( "Couldn't set outfile buffer to %u bytes.\n",
                   outsize );
        exit ( 1 );
    }

    /* do it 记初始时间 循环逐个字符写入 记结束时间 返回耗时 */

    get_clock_ticks ( starttime );    /* 调用上面的宏定义 */
    while (( c = fgetc ( infile )) != EOF )
        fputc ( c, outfile );
    get_clock_ticks ( donetime );
    fclose ( infile );
    fclose ( outfile );

    return ( donetime - starttime );
}


int main ( int argc, char *argv[] )
/*接收参数 源文件名、目标文件名、输入缓冲区大小、输出缓冲区大小（此参数可不传则默认输出缓冲区大小
等于输入缓冲区大小） 实现在多给条件下多次复制文件并最终返回单次复制的平均耗时、最短耗时、最长耗时
和初始条件。*/
{
    size_t insize, outsize;
    int    i;
    long   total, average, lo, hi, elapsed;


    insize = outsize = DEF_BUF;
    /* 审核传参是否符合要求 */
    if ( argc < 3 || argc > 5 )
    {
        fprintf ( stderr,
         "Usage: BUFSIZE infile outfile [insize [outsize]]\n" );
        return ( EXIT_FAILURE );
    }

    /* get buffer sizes */
    if ( argc > 3 )
         insize = (unsigned) atoi ( argv[3] );

    if ( argc > 4 )
         outsize = (unsigned) atoi ( argv[4] );

    /* now, copy the file five times */
    total = hi = 0;
    lo = LONG_MAX;
    for ( i = 1; ; i++ )
    {
        elapsed = CopyFile ( argv[1], argv[2], insize, outsize );
        if ( elapsed > hi )
            hi = elapsed;
        if ( elapsed < lo )
            lo = elapsed;
        total += elapsed;

        if ( total > 500 ||   /* Change this value depending   */
                              /*   on how long you can wait    */
                 i > 4 )      /* Do 4 passes, if time limit OK */
            break;
    }

    average = total / i;

    printf ( "Average of %4ld ticks (%4ld - %4ld). "
             "Insize = %5u. Outsize = %5u.\n",
             average, lo, hi, insize, outsize );

    return ( EXIT_SUCCESS );
}